#ifndef LONGKEY_BASE_SYSTEM_INFO_H_
#define LONGKEY_BASE_SYSTEM_INFO_H_

#include <Windows.h>
#include <tchar.h>

class SystemInfo
{
public:
	// Find out if the OS is at least Windows 2000
	// Service pack 4. If OS version is less than that
	// will return false, all other cases true.
	static bool OSWin2KSP4OrLater() {
		// Use GetVersionEx to get OS and Service Pack information.
		OSVERSIONINFOEX osviex;
		::ZeroMemory(&osviex, sizeof(osviex));
		osviex.dwOSVersionInfoSize = sizeof(osviex);
		BOOL success = ::GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&osviex));
		// If this failed we're on Win9X or a pre NT4SP6 OS.
		if (!success) {
			return false;
		}

		if (osviex.dwMajorVersion < 5) {
			return false;
		}
		if (osviex.dwMajorVersion > 5) {
			return true;    // way beyond Windows XP.
		}
		if (osviex.dwMinorVersion >= 1) {
			return true;    // Windows XP or better.
		}
		if (osviex.wServicePackMajor >= 4) {
			return true;    // Windows 2000 SP4.
		}

		return false;     // Windows 2000, < SP4.
	}

	// Returns true if the OS is at least XP SP2.
	static bool OSWinXPSP2OrLater();

	// CategorizeOS returns a categorization of what operating system is running,
	// and the service pack level.
	// NOTE: Please keep this in the order of increasing OS versions
	enum OSVersionType {
		OS_WINDOWS_UNKNOWN = 1,
		OS_WINDOWS_9X_OR_NT,
		OS_WINDOWS_2000,
		OS_WINDOWS_XP,
		OS_WINDOWS_SERVER_2003,
		OS_WINDOWS_VISTA,
		OS_WINDOWS_7
	};
	static HRESULT CategorizeOS(OSVersionType* os_version, DWORD* service_pack);
	static const wchar_t* OSVersionTypeAsString(OSVersionType t);

	// Returns true if the current operating system is Windows 2000.
	static bool IsRunningOnW2K();

	// Are we running on Windows XP or later.
	static bool IsRunningOnXPOrLater();

	// Are we running on Windows XP SP1 or later.
	static bool IsRunningOnXPSP1OrLater();

	// Are we running on Windows Vista or later.
	static bool IsRunningOnVistaOrLater();

	static bool IsRunningOnVistaRTM();

	// Returns the version and the name of the operating system.
	static bool GetSystemVersion(int* major_version,
		int* minor_version,
		int* service_pack_major,
		int* service_pack_minor,
		TCHAR* name_buf,
		size_t name_buf_len);

	// Returns the processor architecture. We use wProcessorArchitecture in
	// SYSTEM_INFO returned by ::GetNativeSystemInfo() to detect the processor
	// architecture of the installed operating system. Note the "Native" in the
	// function name - this is important. See
	// http://msdn.microsoft.com/en-us/library/ms724340.aspx.
	static DWORD GetProcessorArchitecture();

	// Returns whether this is a 64-bit Windows system.
	static bool Is64BitWindows();
};

#endif	// LONGKEY_BASE_SYSTEM_INFO_H_